package svm;

import java.awt.Point;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import exception.SessionDirectoryNotFoundException;

import utils.Logger;
import utils.Utils;

import au.AU;
import au.AU.Label;


public class Training extends SvmContext {

	// Public API
	
	/*
	 * Creates the training context file
	 * @params: luxandDataFilePath - text file where the training samples are stored 
	 * 
	 * */
	public Training(String parentDirPath, List<AU> aus) {
		super(parentDirPath, aus);
		// TODO Auto-generated constructor stub
	}
		
	/*
	 * Creates training data file and runs SVM
	 * @params: aus - list of AUs that the training has to be performed for
	 * 
	 * */
	public void trainForAUs(List<AU> aus) {
		File trainingDataFile;
		int positiveCount;
		int negativeCount;
		for(AU au: aus) {

			// Creating training data file
			trainingDataFile = new File("data/train_" + au.getLabel().toString());
			try {
				if(!trainingDataFile.exists()) trainingDataFile.createNewFile();
				Utils.clearFile(trainingDataFile);
			} catch (IOException e) {
				e.printStackTrace();
			}

			// Adding positive vectors if current AU's label is contained by current row
			positiveCount = 0;
			for(Session.SessionFrame row: sessionList.get(0).getSessionFrames()) {
				if(row.trainingAuLabels.contains(au.getLabel().toString())) {
					double[] featureVector = au.getFeatureVectorByFacialFeatures(row.points);
					if(featureVector != null) { 
						Utils.writeFile(trainingDataFile, 1, featureVector);
						positiveCount++;
					}
					//Logger.log("Training " + au.getLabel() + ": adding " + row.fileName + "as " + positiveCount + ". positive.");
				}
			}

			// Adding negative vectors if current AU's negative labels and current row's AUs have non null intersection
			negativeCount = 0;
			for(Session.SessionFrame row: sessionList.get(0).getSessionFrames()) {
				if(negativeCount == positiveCount) break;
				List tmp = new ArrayList<String>();
				tmp.addAll(row.trainingAuLabels);
				tmp.retainAll(au.getNegatives());
				if(!tmp.isEmpty() && !row.trainingAuLabels.contains(au.getLabel().toString())) {
					double[] featureVector = au.getFeatureVectorByFacialFeatures(row.points);
					if(featureVector != null) {
						Utils.writeFile(trainingDataFile, -1, featureVector);
						negativeCount++;
					}
					//Logger.log("Training " + au.getLabel() + ": adding " + row.fileName + "as " + negativeCount + ". negative.");
				}
			}
			
		}

		// Running SVM Train by AU's optimalized parameters
		for (Label label: AU.Label.values()) Logger.log("training", Utils.runCmd("svm-train " + label.getParams() + " data/train_" + label + " data/train_" + label + ".model"));
	}
	
	@Override
	public void loadLuxandData(HashMap<String, String> keywords) {
		String luxandDataFilePath = parentDir.getAbsolutePath() + "/luxand_data";
		try {
			sessionList.add(new Session(luxandDataFilePath, null, this));
		} catch (SessionDirectoryNotFoundException e) {
		}
	}
	
}
